package com.test.utils.jira;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class JiraClient {
    private final String jiraUrl;
    private final String personalToken;
    private final boolean sslVerify;
    private final OkHttpClient httpClient;
    private final ObjectMapper objectMapper;

    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");

    public JiraClient(String jiraUrl, String personalToken, boolean sslVerify) {
        this.jiraUrl = jiraUrl.endsWith("/") ? jiraUrl.substring(0, jiraUrl.length() - 1) : jiraUrl;
        this.personalToken = personalToken;
        this.sslVerify = sslVerify;
        this.objectMapper = new ObjectMapper();

        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        if (!sslVerify) {
            try {
                final javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[] {
                    new javax.net.ssl.X509TrustManager() {
                        @Override
                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {}

                        @Override
                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {}

                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return new java.security.cert.X509Certificate[]{};
                        }
                    }
                };

                final javax.net.ssl.SSLContext sslContext = javax.net.ssl.SSLContext.getInstance("SSL");
                sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

                final javax.net.ssl.SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

                builder.sslSocketFactory(sslSocketFactory, (javax.net.ssl.X509TrustManager)trustAllCerts[0]);
                builder.hostnameVerifier((hostname, session) -> true);
            } catch (Exception e) {
                //
            }
        }
        this.httpClient = builder.build();
    }

    public String createIssue(String projectKey, String issueType, String summary,
                            String description, String priority, List<String> labels) throws IOException {
                                return createIssue(projectKey, issueType, summary, description, priority, labels, null);
    }

    public String createIssue(String projectKey, String issueType, String summary,
                            String description, String priority, List<String> labels,
                            Map<String, Object> customFields) throws IOException {
        Map<String, Object> fields = new HashMap<>();
        fields.put("project", Map.of("key", projectKey));
        fields.put("summary", summary);
        fields.put("description", description);
        fields.put("issueType", Map.of("name", issueType));

        if (priority != null && !priority.isEmpty()) {
            fields.put("priority", Map.of("name", priority));
        }

        if (labels != null && !labels.isEmpty()) {
            fields.put("labels", labels);
        }

        if (customFields != null) {
            fields.putAll(customFields);
        }

        Map<String, Object> issueData = Map.of("fields", fields);

        String jsonPayload = objectMapper.writeValueAsString(issueData);

        RequestBody body = RequestBody.create(jsonPayload, JSON);
        Request request = new Request.Builder()
            .url(jiraUrl + "/rest/api/2/issue")
            .header("Authorization", "Bearer " + personalToken)
            .header("Accept", "application/json")
            .post(body)
            .build();

        try (Response response = httpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Failed to create JIRA issue: " + response.code() + " - " + response.body().string());
            }

            JsonNode responseJson = objectMapper.readTree(response.body().string());
            return responseJson.get("key").asText();
        }
    } 

    public boolean addAttachment(String issueKey, File file) throws IOException {
        if (!file.exists()) {
            throw new IOException("File does not exist: " + file.getAbsolutePath());
        }

        RequestBody requestBody = new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart("file", file.getName(),
                RequestBody.create(file, MediaType.parse("application/octet-stream")))
            .build();
        
        Request request = new Request.Builder()
            .url(jiraUrl + "/rest/api/2/issue/" + issueKey + "/attachments")
            .header("Authorization", "Bearer " + personalToken)
            .header("X-Atlassian-Token", "no-check")
            .post(requestBody)
            .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                System.err.println("Failed to add attachment: " + response.code() + " - " + response.body().string());
                return false;
            }
            return true;
        }
    }

    public boolean addComment(String issueKey, String comment) throws IOException {
        Map<String, String> commentData = Map.of("body", comment);
        String jsonPayload = objectMapper.writeValueAsString(commentData);

        RequestBody body = RequestBody.create(jsonPayload, JSON);
        Request request = new Request.Builder()
            .url(jiraUrl + "/rest/api/2/issue/" + issueKey + "/comment")
            .header("Authorization", "Bearer " + personalToken)
            .header("Accept", "application/json")
            .post(body)
            .build();

        try (Response response = httpClient.newCall(request).execute()) {
            return response.isSuccessful();
        }
    }

    public JsonNode getIssue(String issueKey) throws IOException {
        Request request = new Request.Builder()
            .url(jiraUrl + "/rest/api/2/issue" + issueKey)
            .header("Authorization", "Bearer " + personalToken)
            .header("Accept", "application/json")
            .get()
            .build();

        try (Response response = httpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Failed to get JIRA issue: " + response.code());
            }

            return objectMapper.readTree(response.body().string());
        }
    }
}
